package com.wbsxch.shiro.config;

import com.wbsxch.shiro.common.ShiroUtils;
import com.wbsxch.shiro.shiro.ShiroRealm;
import com.wbsxch.shiro.shiro.ShiroSessionManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: 快乐在角落里
 * @create: 2018-11-08 16:28
 */
@Configuration
public class ShiroConfiguration {

    @Bean
    public ShiroFilterFactoryBean shiroFilter(){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager());
        shiroFilter.setLoginUrl(loginUrl);
        shiroFilter.setFilterChainDefinitionMap(map);
        return shiroFilter;
    }

    /**
     * 安全管理器
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        securityManager.setSessionManager(sessionManager());
        securityManager.setCacheManager(cacheManager());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     * realm
     */
    @Bean
    public ShiroRealm shiroRealm(){
        ShiroRealm shiroRealm = new ShiroRealm();
        shiroRealm.setCredentialsMatcher(matcher());
        return shiroRealm;
    }

    /**
     * 加密
     * @return
     */
    @Bean
    public HashedCredentialsMatcher matcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName(ShiroUtils.HASH_ALGORITHM);
        matcher.setHashIterations(ShiroUtils.HASH_ITERATIONS);
        return matcher;
    }

    /**
     * Session管理器
     */
    @Bean
    public SessionManager sessionManager(){
        ShiroSessionManager sessionManager = new ShiroSessionManager();
        sessionManager.setSessionDAO(sessionDAO());
        return sessionManager;
    }

    /**
     * 缓存管理器
     */
    @Bean
    public CacheManager cacheManager(){
        RedisCacheManager cacheManager = new RedisCacheManager();
        cacheManager.setRedisManager(redisManager());
        //设置缓存的key前缀
        cacheManager.setKeyPrefix(cachePrefix);
        //设置缓存的key后缀
        cacheManager.setPrincipalIdFieldName(cacheSuffix);
        cacheManager.setExpire(cacheExpire);
        return cacheManager;
    }

    /**
     * RedisSessionDAO
     */
    @Bean
    public SessionDAO sessionDAO(){
        RedisSessionDAO sessionDAO = new RedisSessionDAO();
        sessionDAO.setRedisManager(redisManager());
        sessionDAO.setExpire(sessionExpire);
        sessionDAO.setKeyPrefix(sessionPrefix);
        return sessionDAO;
    }

    /** Redis连接管理 */
    @Bean
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host+":"+port);
        redisManager.setPassword(password);
        redisManager.setDatabase(database);
        redisManager.setTimeout(timeout);//超时时间，尝试连接redis的时间
        return redisManager;
    }

    @Bean
    public RememberMeManager rememberMeManager(){
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.setCookie(cookie());
        return rememberMeManager;
    }

    @Bean
    public Cookie cookie(){
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName(rememberMeName);
        simpleCookie.setMaxAge(maxAge);//单位秒 设置为7天
        return simpleCookie;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor advisor(){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager());
        return advisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator creator(){
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        /** 设置是否直接代理目标类，而不只是代理特定的接口 */
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private Integer port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.timeout}")
    private Integer timeout;

    @Value("${shiro.session.expire}")
    private Integer sessionExpire;

    @Value("${shiro.session.prefix}")
    private String sessionPrefix;

    @Value("${shiro.cache.expire}")
    private Integer cacheExpire;

    @Value("${shiro.cache.prefix}")
    private String cachePrefix;

    @Value("${shiro.cache.suffix}")
    private String cacheSuffix;

    @Value("${shiro.database}")
    private Integer database;

    @Value("#{${shiro.filter.map}}")
    public Map<String,String> map = new LinkedHashMap<>();

    @Value("${shiro.login.url}")
    public String loginUrl;

    @Value("${shiro.rememberMe.name}")
    public String rememberMeName;

    @Value("${shiro.rememberMe.maxAge}")
    public Integer maxAge;
}
